#ifndef __SUB__HPP__
#define __SUB__HPP__

// Sub explicitly converted to Add and the sign is propagated to the term to
// make it +/- 
template< class A, class B>
constexpr Expression<BinaryExpression<Expression<A>, Expression<B>, Add> >
operator-(Expression<A> a, Expression<B> b)
{
  typedef BinaryExpression <Expression<A>, Expression<B>, Add> ExprT;
  return Expression<ExprT>(ExprT(a,-b));
}

// Can we do without this ? Specializations don't overload !
template <int PLACE, class A, bool B>
constexpr Expression<BinaryExpression<Expression<A>, Term<PLACE, Var, B>, Add> >
operator-(Expression<A> a, Term<PLACE, Var, B> b)
{
  typedef BinaryExpression <Expression<A>, Term<PLACE, Var, B>, Add> ExprT;
  return Expression<ExprT>(ExprT(a,-b));
}

// Can we do without this ? Specializations don't overload !
template <int PLACE, bool A, class B>
constexpr Expression<BinaryExpression<Term<PLACE, Var, A>, Expression<B>, Add> >
operator-(Term<PLACE, Var, A> a, Expression<B> b)
{
  typedef BinaryExpression <Term<PLACE, Var, A>, Expression<B>, Add> ExprT;
  return Expression<ExprT>(ExprT(a,-b));
}

// Can we do without this ? Specializations don't overload !
template <int PLACEA, int PLACE, bool A, bool B>
constexpr Expression<BinaryExpression<Term<PLACEA, Var, A>, Term<PLACE, Var, B>, Add> >
operator-(Term<PLACEA, Var, A> a, Term<PLACE, Var, B> b)
{
  typedef BinaryExpression <Term<PLACEA, Var, A>, Term<PLACE, Var, B>, Add> ExprT;
  return Expression<ExprT>(ExprT(a,-b));
}

// Can we do without this ? Specializations don't overload !
template <class A>
constexpr Expression<BinaryExpression<Expression<A>, ConstantTerm, Add> >
operator-(Expression<A> const & a, int const & b)
{
  typedef BinaryExpression <Expression<A>, ConstantTerm, Add> ExprT;
  return Expression<ExprT>(ExprT(a,ConstantTerm(-b)));
}

// Can we do without this ? Specializations don't overload !
template <class B>
constexpr Expression<BinaryExpression<ConstantTerm, Expression<B>, Add> >
operator-(int const & a, Expression<B> const & b)
{
  typedef BinaryExpression <ConstantTerm, Expression<B>, Add> ExprT;
  return Expression<ExprT>(ExprT(ConstantTerm(a),--b));
}

template<int PLACEA, int PLACE>
constexpr Expression<BinaryExpression<Expression<VariableTerm<PLACEA> >,
                            Expression<VariableTerm<PLACE> >, Add> >
operator-(VariableTerm<PLACE> const & a, VariableTerm<PLACE> const & b) {
  typedef BinaryExpression <Expression<VariableTerm<PLACEA> >, Expression<VariableTerm<PLACE> >, Add> ExprT;
  return Expression<ExprT>(ExprT(Expression<VariableTerm<PLACEA> >(a),
                                 Expression<VariableTerm<PLACE > >(-b)));
}
template<int PLACE>
constexpr Expression<BinaryExpression<Expression<ConstantTerm>, Expression<VariableTerm<PLACE> >, Add> >
operator-(ConstantTerm const & a, VariableTerm<PLACE> const & b) {
  typedef BinaryExpression <Expression<ConstantTerm>, Expression<VariableTerm<PLACE> >, Add> ExprT;
  return Expression<ExprT>(ExprT(Expression<ConstantTerm>(a),
                                 Expression<VariableTerm<PLACE> >(-b)));
}
template<int PLACE>
constexpr Expression<BinaryExpression<Expression<VariableTerm<PLACE> >, Expression<ConstantTerm>, Add> >
operator-(VariableTerm<PLACE> const & b, ConstantTerm const & a) {
  typedef BinaryExpression <Expression<VariableTerm<PLACE> >, Expression<ConstantTerm>, Add> ExprT;
  return Expression<ExprT>(ExprT(Expression<VariableTerm<PLACE> >(b), 
                                 Expression<ConstantTerm>(-a)));
}
template<int PLACE>
constexpr Expression<BinaryExpression<Expression<ConstantTerm>, Expression<ConstantTerm>, Add> >
operator-(ConstantTerm const & b, ConstantTerm const & a) {
  typedef BinaryExpression <Expression<ConstantTerm>, Expression<ConstantTerm>, Add> ExprT;
  return Expression<ExprT>(ExprT(Expression<ConstantTerm>(b), 
                                 Expression<ConstantTerm>(-a)));
}

#endif //__SUB__HPP__
